package org.odst.util;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
import org.odftoolkit.odfdom.doc.table.OdfTable;
import org.odftoolkit.odfdom.doc.table.OdfTableCell;
import org.odftoolkit.odfdom.doc.table.OdfTableRow;
import org.odst.tag.Block;
import org.w3c.dom.Node;

/**
 * @author Leonid Vysochyn
 * @author Cyril PODER
 */
public class TagBodyHelper {
    protected static final Log log = LogFactory.getLog(TagBodyHelper.class);

    public static int duplicateDown(OdfTable sheet, Block block, int n) {
        if (n > 0) {
        	for (int i=1;i<=n;i++) {
        		for (int row=block.getStartRowNum();row<=block.getEndRowNum();row++) {
        			Node newRow = sheet.getRowByIndex(row).getOdfElement().cloneNode(true);
        			OdfTableRow destRow = sheet.getRowByIndex(row + i * block.getNumberOfRows());
        			if (destRow != null)
        				sheet.getOdfElement().insertBefore(newRow, destRow.getOdfElement());
        			else
        				sheet.getOdfElement().appendChild(newRow);
        		}
        	}
            return block.getNumberOfRows() * n;
        }
        return 0;
    }

    public static int duplicateRight(OdfTable sheet, Block block, int n) {
        if (n > 0) {
        	OdfTableRow row = sheet.getRowByIndex(block.getStartRowNum());
        		while (row != null && row.getRowIndex() <= block.getEndRowNum()) {
                	for (int i=1;i<=n;i++) {
                		for (int j=block.getEndCellNum();j>=block.getStartCellNum();j--) {
                			Node newCell = row.getCellByIndex(block.getStartCellNum()).getOdfElement().cloneNode(true);
                			OdfTableCell target = row.getCellByIndex(block.getEndCellNum() + 1);
                			if (target == null)
                				row.getOdfElement().appendChild(newCell);
                			else
                				row.getOdfElement().insertBefore(newCell, target.getOdfElement());
                    	}
            		}
        			row = row.getNextRow();
        		}
            return block.getNumberOfColumns() * n;
        }
        return 0;
    }

    public static void replaceProperty(OdfTable sheet, Block block, String oldProperty, String newProperty) {
        for (int i = block.getStartRowNum(); i <= block.getEndRowNum(); i++) {
        	OdfTableRow row = sheet.getRowByIndex(i);
        	for (int j = 0; j < row.getCellCount(); j++) {
	            try {
					replacePropertyInCell(row.getCellByIndex(j), oldProperty, newProperty);
				} catch (IndexOutOfBoundsException e) {
					e.printStackTrace();
				}
        	}
        }
    }

    private static void replacePropertyInCell(OdfTableCell cell, String oldProperty, String newProperty) {
        if (cell != null /*&& cell.getType().equals(CellContentType.TEXT)*/) {
            String cellValue = cell.getStringValue();
            String newValue = cellValue.replaceAll(oldProperty, newProperty);
            cell.setStringValue(newValue);
        }
    }

    public static void removeBorders(OdfTable sheet, Block block) {
    	sheet.getOdfElement().removeChild(sheet.getRowByIndex(block.getEndRowNum()).getOdfElement());
//        deleteRow(sheet, sheet.getRow(block.getStartRowNum()));
    	sheet.getOdfElement().removeChild(sheet.getRowByIndex(block.getStartRowNum()).getOdfElement());
//        deleteRow(sheet, sheet.getRow(block.getEndRowNum()));
        block.setEndRowNum(block.getEndRowNum() - 2);
//        shift(sheet, block, -1);
//        if (block.getEndRowNum() + 2 < sheet.getLastRowNum()) {
//            Util.shiftRows(sheet, block.getEndRowNum() + 3, sheet.getLastRowNum(), -2);
//        }
    }

    public static void removeLeftRightBorders(OdfTable sheet, Block block) {
        OdfTableRow currentRow = sheet.getRowByIndex(block.getStartRowNum());
        while (currentRow != null && currentRow.getRowIndex() <= block.getEndRowNum()) {
        	currentRow.getOdfElement().removeChild(currentRow.getCellByIndex(block.getEndCellNum()).getOdfElement());
        	currentRow.getOdfElement().removeChild(currentRow.getCellByIndex(block.getStartCellNum()).getOdfElement());
        	currentRow.getOdfElement().newTableTableCellElement();
        	currentRow.getOdfElement().newTableTableCellElement();
        	currentRow = currentRow.getNextRow();
        }
//        OdfTableRow row = sheet.getRowByIndex(block.getStartRowNum());
//        Util.shiftCellsLeft(sheet, block.getStartRowNum(), (int) (block.getStartCellNum() + 1),
//                block.getEndRowNum(), row.getCellCount() - 1, (int) 1);
//        Util.shiftCellsLeft(sheet, block.getStartRowNum(), block.getEndCellNum(), block.getEndRowNum(), row.getCellCount() - 1, (int) 1);
        block.setEndCellNum((int) (block.getEndCellNum() - 2));
    }

    private static void clearAndRemoveCell(OdfTableRow row, OdfTableCell cellToRemove) {
        clearCell(cellToRemove);
//        if (cellToRemove != null) {
//            row.removeCell(cellToRemove);
//        }
    }

//    public static void shift(OdfTable sheet, Block block, int n) {
//        Util.shiftRows(sheet, block.getStartRowNum(), block.getEndRowNum(), n);
//        block.setStartRowNum(block.getStartRowNum() + n);
//        block.setEndRowNum(block.getEndRowNum() + n);
//
//    }


    public static void removeRowCells(OdfTableRow row, int startCellNum, int endCellNum) {
        //clearRowCells(row, startCellNum, endCellNum);
//        Util.shiftCellsLeft(sheet, row.getRowIndex(), (int) (endCellNum + 1), row.getRowIndex(), row.getCellCount() - 1, (int) (endCellNum - startCellNum + 1));
        //clearRowCells(row, (int) (row.getRangeAddress().EndColumn - (endCellNum - startCellNum)), row.getRangeAddress().EndColumn);
    	int nbCells = endCellNum - startCellNum + 1;
    	for (int i=0;i<nbCells;i++) {
    		OdfTableCell odfTableCell = row.getCellByIndex(startCellNum);
    		if (odfTableCell != null)
    			row.getOdfElement().removeChild(odfTableCell.getOdfElement());
    	}
    }

    public static void removeBodyRows(OdfTable sheet, Block block) {
       	sheet.removeRowsByIndex(block.getStartRowNum(), block.getNumberOfRows());
//            removeMergedRegions(sheet, row);
//        Util.shiftRows(sheet, block.getEndRowNum() + 1, sheet.getLastRowNum(), -block.getNumberOfRows());
    }

//    private static void removeMergedRegions(Sheet sheet, Row row) {
//        if (row != null) {
//            int i = row.getRowNum();
//            for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {
//                Util.removeMergedRegion(sheet, i, j);
//            }
//        }
//    }

    static void clearRow(OdfTableRow row) {
        if (row != null) {
            for (int i = 0; i < row.getCellCount(); i++) {
                try {
					clearCell(row.getCellByIndex(i));
				} catch (IndexOutOfBoundsException e) {
					e.printStackTrace();
				}
            }
        }
    }

    static void clearRowCells(OdfTableRow row, int startCell, int endCell) {
        if (row != null) {
            for (int i = startCell; i <= endCell; i++) {
                try {
					clearCell(row.getCellByIndex(i));
				} catch (IndexOutOfBoundsException e) {
					e.printStackTrace();
				}
            }
        }
    }

    static void clearCell(OdfTableCell cell) {
    	cell.setStringValue("");
    }

    public static void adjustFormulas(OdfSpreadsheetDocument hssfWorkbook, OdfTable hssfSheet, Block body) {
        for (int i = body.getStartRowNum(); i <= body.getEndRowNum(); i++) {
        	OdfTableRow row = hssfSheet.getRowByIndex(i);
            adjustFormulas(row);
        }
    }

    private static void adjustFormulas(OdfTableRow row) {
    	int rowIndex = row.getRowIndex();
        if (row != null) {
            for (int i = 0; i < row.getCellCount(); i++) {
				try {
					OdfTableCell cell = row.getCellByIndex(i);
	                if (cell != null /*&& cell.getType().equals(CellContentType.TEXT)*/ && cell.getStringValue().matches("\\$\\[.*?\\]")) {
	                    String cellValue = cell.getStringValue();
	                    String[] parts = cellValue.split("\\$\\[.*?\\]");
	                    String newCellValue = parts[0];
	                    newCellValue = newCellValue.replaceAll("#", Integer.toString(rowIndex + 1));

	                    cell.setStringValue(newCellValue);
	                }
				} catch (IndexOutOfBoundsException e) {
					e.printStackTrace();
				}
            }
        }
    }
}
